#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
#include "record.h"

snd_pcm_t *capture = NULL;
FILE *file = NULL;
char *buffer = NULL;
int recording = 0; // 录音状态标志

int open_pcm_device(snd_pcm_t **capture, const char *device, snd_pcm_format_t format, unsigned int rate, int channels, snd_pcm_uframes_t frames) {
    int err;
    snd_pcm_hw_params_t *hw_params;
    
    // 打开PCM设备
    if ((err = snd_pcm_open(capture, device, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
        fprintf(stderr, "无法打开PCM设备：%s\n", snd_strerror(err));
        return ERROR_PCM_OPEN_FAILED;
    }

    // 分配硬件参数结构体
    snd_pcm_hw_params_alloca(&hw_params);

    // 初始化硬件参数
    if ((err = snd_pcm_hw_params_any(*capture, hw_params)) < 0) {
        fprintf(stderr, "无法初始化硬件参数：%s\n", snd_strerror(err));
        snd_pcm_close(*capture);
        return ERROR_HW_PARAMS_FAILED;
    }

    // 设置访问类型
    if ((err = snd_pcm_hw_params_set_access(*capture, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
        fprintf(stderr, "无法设置访问类型：%s\n", snd_strerror(err));
        snd_pcm_close(*capture);
        return ERROR_HW_PARAMS_FAILED;
    }

    // 设置采样格式
    if ((err = snd_pcm_hw_params_set_format(*capture, hw_params, format)) < 0) {
        fprintf(stderr, "无法设置采样格式：%s\n", snd_strerror(err));
        snd_pcm_close(*capture);
        return ERROR_HW_PARAMS_FAILED;
    }

    // 设置通道数
    if ((err = snd_pcm_hw_params_set_channels(*capture, hw_params, channels)) < 0) {
        fprintf(stderr, "无法设置通道数：%s\n", snd_strerror(err));
        snd_pcm_close(*capture);
        return ERROR_HW_PARAMS_FAILED;
    }

    // 设置采样率
    if ((err = snd_pcm_hw_params_set_rate_near(*capture, hw_params, &rate, NULL)) < 0) {
        fprintf(stderr, "无法设置采样率：%s\n", snd_strerror(err));
        snd_pcm_close(*capture);
        return ERROR_HW_PARAMS_FAILED;
    }

    // 设置每个周期的帧数
    if ((err = snd_pcm_hw_params_set_period_size_near(*capture, hw_params, &frames, NULL)) < 0) {
        fprintf(stderr, "无法设置周期帧数：%s\n", snd_strerror(err));
        snd_pcm_close(*capture);
        return ERROR_HW_PARAMS_FAILED;
    }

    // 应用硬件参数
    if ((err = snd_pcm_hw_params(*capture, hw_params)) < 0) {
        fprintf(stderr, "无法应用硬件参数：%s\n", snd_strerror(err));
        snd_pcm_close(*capture);
        return ERROR_HW_PARAMS_FAILED;
    }

    return 0; // 成功返回0
}

int start_recording(const char *filename, snd_pcm_uframes_t frames, int channels) {
    int err;

    // 打开输出文件
    if ((file = fopen(filename, "wb")) == NULL) {
        fprintf(stderr, "无法打开输出文件\n");
        snd_pcm_close(capture);
        return ERROR_PCM_WRITE_FAILED;
    }

    // 分配缓冲区
    buffer = (char *)malloc(snd_pcm_frames_to_bytes(capture, frames));
    if (!buffer) {
        fprintf(stderr, "无法分配缓冲区内存\n");
        fclose(file);
        snd_pcm_close(capture);
        return ERROR_PCM_WRITE_FAILED;
    }

    recording = 1;
    return 0; // 成功返回0
}

void stop_recording() {
    if (recording) {
        recording = 0;
        free(buffer);
        fclose(file);
        snd_pcm_close(capture);
        printf("录音结束\n");
    }
}

void handle_recording(snd_pcm_uframes_t frames) {
    int err;

    if (recording) {
        err = snd_pcm_readi(capture, buffer, frames);
        if (err < 0) {
            if (err == -EPIPE) {
                // 缓冲区溢出
                snd_pcm_prepare(capture);
            } else {
                fprintf(stderr, "采集音频失败：%s\n", snd_strerror(err));
                stop_recording();
                return;
            }
        }

        // 写入文件
        if (fwrite(buffer, snd_pcm_frames_to_bytes(capture, frames), 1, file) != 1) {
            fprintf(stderr, "写入文件失败\n");
            stop_recording();
        }
    }
}
